﻿


using IotContract.Dtos.Clients;
using IotContract.Dtos.Remotes.Request;
using IotContract.Dtos.Servers.Pushs;
using IotContract.Enums;
using IotContract.Interfaces;
using IotContract.Interfaces.Process;
using IotContract.Models.Clients;
using IotContract.Models.Process;
using IotServerService.Services.Mqtts;
using Microsoft.Extensions.DependencyInjection;
using MQTTnet.Server;

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting;
using System.Text;
using System.Threading.Tasks;
using XT.Common.Extensions;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace IotServerService.Services.Datas.Managers;
/// <summary>
/// 服务管理入口
/// </summary>
public class ServerMainManager : IServerMainManager
{
    private IEnumerable<IServerDataManager> _managers;
    private readonly IServiceProvider _provider;
   
    /// <summary>
    /// 程序控制指令,设备控制指令，设备id=0为程序控制指令
    /// </summary>
    ConcurrentDictionary<long, ConcurrentQueue<ClientControlCommand>> ProgramCommands = new ConcurrentDictionary<long, ConcurrentQueue<ClientControlCommand>>();


    public ServerMainManager(IEnumerable<IServerDataManager> managers,IServiceProvider provider)
    {
        _managers = managers;
        _provider = provider;
       
    }
    /// <summary>
    /// 获取设备信息
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public async Task<List<T>> GetEquips<T>(ClientRequestCommand command) where T:IPushEquip
    {
        if(command.ProtobufType.IsNotNullOrEmpty())
        {
            var manager= _managers.FirstOrDefault(x=>x.ProtobufType==command.ProtobufType);
            if (manager != null)
            {
                var equips= await manager.GetEquips(command);
                return equips.ConvertAll(x => (T)x);
            }
        }
        return new List<T>();
    }

   
    /// <summary>
    /// 获取所有设备通用数据
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    public async Task<List<T>> GetEquips<T>(List<ClientRequestCommand> commands) where T : IPushEquip
    {
        List<IPushEquip> list = new List<IPushEquip>();
        var protobufDic= commands.ToLookup(x => x.ProtobufType).ToDictionary(x => x.Key, y => y.ToList());
        foreach(var protobuf in protobufDic.Keys)
        {
            var manager = _managers.FirstOrDefault(x => x.ProtobufType == protobuf);
            if (manager != null)
            {
                var equips = await manager.GetEquips(protobufDic[protobuf]);
                list.AddRange(equips);
            }
        }
        return list.ConvertAll(x => (T)x);
    }
    /// <summary>
    /// 推送设备
    /// </summary>
    /// <param name="equipList"></param>
    /// <returns></returns>
    public async Task<List<OperationWriteCommand>> PushEquips(List<IPushEquip> equipList) 
    {
        if(equipList==null || equipList.Count == 0)
        {
            return new List<OperationWriteCommand>();
        }
        else
        {
            // 批量设备协议类型相同
            var proto = equipList.FirstOrDefault().ProtobufType;
            var manager = _managers.FirstOrDefault(x => x.ProtobufType == proto);
            if (manager != null)
            {
                var datas=await manager.PushEquips(equipList);
                return datas;
            }
            else
            {
                return new List<OperationWriteCommand>();
            }
           
        }
       
    }

    /// <summary>
    /// 添加控制命
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public async Task<bool> AddControl(ClientControlCommand command)
    {
        if (command.ProgramId == 0)
        {
            return false;
        }
       
        ProgramCommands.TryGetValue(command.ProgramId, out var commans);

        if(commans == null)
        {
            commans = new ConcurrentQueue<ClientControlCommand>();
            ProgramCommands.TryAdd(command.ProgramId, commans);
            
        }

        
       
        commans.Enqueue(command);
        return true;
    }



    /// <summary>
    /// 读取所有程序控制指令
    /// </summary>
    /// <param name="programId"></param>
    /// <param name="equipId"></param>
    /// <returns></returns>
    public async Task<ConcurrentQueue<ClientControlCommand>> ReadControl(long programId)
    {
        if (!ProgramCommands.ContainsKey(programId))
        {

             return new ConcurrentQueue<ClientControlCommand>();
        }
        else
        {


            ProgramCommands.TryGetValue(programId, out var commands);
            // 移除控制指令
            ProgramCommands.TryRemove(programId, out _);




            return commands;
        }
    }

    /// <summary>
    /// 添加写入指令
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    public async Task<bool> AddWrite(OperationWriteCommand command)
    {
        if (command.ProtobufType.IsNotNullOrEmpty())
        {
            var manager = _managers.FirstOrDefault(x => x.ProtobufType == command.ProtobufType);
            if (manager != null)
            {
               return await manager.AddWrite(command);
               
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    /// <summary>
    /// 添加写入指令
    /// </summary>
    /// <param name="commands"></param>
    /// <returns></returns>
    public async Task<bool> AddWrites(IEnumerable<OperationWriteCommand> commands)
    {
        if (commands==null || commands.Count() == 0)
        {
            return false;
        }
        var protobuType = commands.FirstOrDefault()?.ProtobufType;
        if (protobuType.IsNotNullOrEmpty())
        {
            var manager = _managers.FirstOrDefault(x => x.ProtobufType == protobuType);
            if (manager != null)
            {
                return await manager.AddWrites(commands);

            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    /// <summary>
    /// 添加报警
    /// </summary>
    /// <param name="warns"></param>
    /// <returns></returns>
    public async Task<bool> AddWarns(IEnumerable<IotEquipWarnDto> warns)
    {
        if (warns == null || warns.Count() == 0)
        {
            return false;
        }
        var protobuType = warns.FirstOrDefault()?.ProtobufType;
        if (protobuType.IsNotNullOrEmpty())
        {
            var manager = _managers.FirstOrDefault(x => x.ProtobufType == protobuType);
            if (manager != null)
            {
                return await manager.AddWarns(warns);

            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    /// <summary>
    /// 获取进程调度数据
    /// </summary>
    /// <param name="provider"></param>
    /// <returns></returns>
   public async Task<List<ProcessBaseData>> GetProcessDatas(ProcessProviderCommand provider)
    {
        try
        {
            var process= _provider.GetService<IProcessOpenProvider>();
            if (process == null)
            {
                return new List<ProcessBaseData>();
            }
            switch (provider.ProviderType)
            {
                case IotContract.Enums.ProcessProviderType.None:
                    break;
                case IotContract.Enums.ProcessProviderType.EnterJob:
                    var ejobs= process.GetJobs(ProcessProviderType.EnterJob);
                    if (provider.Nums.IsNotNullOrEmpty())
                    {
                        ejobs = ejobs.Where(x => provider.Nums.Contains(x.Num.ToString())).ToList();
                    }
                    return ejobs;

                case IotContract.Enums.ProcessProviderType.OutJob:
                    var ojobs= process.GetJobs(ProcessProviderType.OutJob);
                    if (provider.Nums.IsNotNullOrEmpty())
                    {
                        ojobs = ojobs.Where(x => provider.Nums.Contains(x.Num.ToString())).ToList();
                    }
                    return ojobs;

                case IotContract.Enums.ProcessProviderType.MoveJob:
                    var mjobs= process.GetJobs(ProcessProviderType.MoveJob);
                    if (provider.Nums.IsNotNullOrEmpty())
                    {
                        mjobs = mjobs.Where(x => provider.Nums.Contains(x.Num.ToString())).ToList();
                    }
                    return mjobs;
                case IotContract.Enums.ProcessProviderType.Cv:
                    
                        var cvs = process.GetUnitCVs();
                        if(provider.Nums.IsNotNullOrEmpty())
                        {
                           cvs= cvs.Where(x=>provider.Nums.Contains(x.Num.ToString())).ToList();
                        }
                        return cvs;
                       
                    
                case IotContract.Enums.ProcessProviderType.Sc:
                    var datas = process.GetStackers();
                    if (provider.Nums.IsNotNullOrEmpty())
                    {
                        datas = datas.Where(x => provider.Nums.Contains(x.Num.ToString())).ToList();
                    }
                    return datas;
                case IotContract.Enums.ProcessProviderType.FmtJob:
                    return process.GetJobs(ProcessProviderType.FmtJob);

                case IotContract.Enums.ProcessProviderType.FireJob:
                    var fjobs= process.GetJobs(ProcessProviderType.FireJob);
                    if (provider.Nums.IsNotNullOrEmpty())
                    {
                        fjobs = fjobs.Where(x => provider.Nums.Contains(x.Num.ToString())).ToList();
                    }
                    return fjobs;
                case ProcessProviderType.Other:
                    var others = process.GetOthers(IotEquipType.ALL);
                    if (provider.Nums.IsNotNullOrEmpty())
                    {
                        others = others.Where(x => provider.Nums.Contains(x.Num.ToString())).ToList();
                    }
                    return others;
                default:
                    break;
            }
        }
        catch(Exception ex)
        {
            return new List<ProcessBaseData>();
        }
        return new List<ProcessBaseData>();
    }
    /// <summary>
    /// 添加进程调度任务
    /// </summary>
    /// <param name="process"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<string> AddProcessJob(ProcessBaseData data, ProcessProviderType type)
    {
        try
        {
            var process = _provider.GetService<IProcessOpenProvider>();
            if (process == null)
            {
                return "Please First Run Process";
            }

           return process.AddJob(data, type);

            
           
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }
    /// <summary>
    /// 完成任务
    /// </summary>
    /// <param name="fmsCommitTrayRequest"></param>
    /// <returns></returns>
    public async Task<string> CompleteJob(FmsJobCompleteRequest fmsCommitTrayRequest)
    {
        try
        {
            var process = _provider.GetService<IProcessOpenProvider>();
            if (process == null)
            {
                return "Please First Run Process";
            }

            var result=  await process.CompleteJob(fmsCommitTrayRequest);

            return result;



        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }
    /// <summary>
    /// 移除进程调度任务
    /// </summary>
    /// <param name="data"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public async Task<string> RemoveProcessJob(ProcessBaseData data,ProcessProviderType type)
    {
        try
        {
            var process = _provider.GetService<IProcessOpenProvider>();
            if (process == null)
            {
                return "Please First Run Process";
            }

            return process.RemoveJob(data, type);
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }

    /// <summary>
    /// 执行相关调度数据
    /// </summary>
    /// <param name="data"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public async Task<string> ExecuteProcessData(ProcessBaseData data, ProcessProviderType type)
    {
        try
        {
            var process = _provider.GetService<IProcessOpenProvider>();
            if (process == null)
            {
                return "Please First Run Process";
            }

            await process.ExecuteData(data, type);

            return string.Empty;
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }
    /// <summary>
    /// 清理设备
    /// </summary>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task ClearEquips()
    {
        foreach(var manager in _managers)
        {
           await manager.ClearEquips();
        }
    }

    /// <summary>
    /// 初始化相关数据
    /// </summary>
    /// <returns></returns>
   public async Task<string> Initial()
    {

        return string.Empty;
       
    }


}
